﻿///////////////////////////////////////////////////////////////////////////////////////////////
// System.Text.Parsing - © 2012 Sebastien Pellizzari
// Released under the MIT License (http://www.opensource.org/licenses/mit-license.php)
///////////////////////////////////////////////////////////////////////////////////////////////

namespace System.Text.Parsing
{
    /// <summary>Represents options for a scanned token.</summary>
    [Flags]
    public enum TokenOptions
    {
        /// <summary>Represents no options.</summary>
        None = 0,
        /// <summary>The token can be safely ignored by the parser.</summary>
        Ignore = 1,
    }

    /// <summary>Defines some constants for token type IDs.</summary>
    public static class TokenTypeIds
    {
        /// <summary>Represents the token type ID for ERROR tokens.</summary>
        public const int Error = 1;
        /// <summary>Represents the token type ID for EOF tokens.</summary>
        public const int EOF = 2;
        /// <summary>Represents the first token type ID for user-defined token types.</summary>
        public const int User = 3;
    }

    /// <summary>Represents a tokenizer context.</summary>
    /// <typeparam name="TRange">The type of token range.</typeparam>
    /// <typeparam name="TTokenValue">The type of token value.</typeparam>
    public interface ITokenizerContext
    {
        /// <summary>Determines whether specified token type is expected by the tokenizer at current stage of the scanning process.</summary>
        /// <param name="tokenTypeId">The ID of the token type.</param>
        /// <returns>true if expected; false otherwise.</returns>
        bool IsExpected(int tokenTypeId);
    }

    /// <summary>Represents a tokenizer.</summary>
    /// <typeparam name="TTokenRange">The type of token range.</typeparam>
    /// <typeparam name="TTokenValue">The type of token value.</typeparam>
    public interface ITokenizer<TTokenRange, TTokenValue>
        where TTokenRange : IDataRange<TTokenRange>
    {
        /// <summary>Returns the next token from the source data.</summary>
        /// <param name="context">The scanning context.</param>
        /// <param name="tokenTypeId">The ID of scanned token type.</param>
        /// <param name="tokenOptions">Options of scanned token.</param>
        /// <param name="tokenRange">The source data range of scanned token.</param>
        /// <param name="tokenValue">Storage for computed token value.</param>
        /// <typeparam name="TContext">The type of scanner context.</typeparam>
        void Scan<TContext>(TContext context, out int tokenTypeId, out TokenOptions tokenOptions, out TTokenRange tokenRange, ref TTokenValue tokenValue)
            where TContext : ITokenizerContext;
    }
}
